﻿using System;
using System.Collections.Generic;

using Gonte.Collections;
using Gonte.Reflection;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace MyUtilitiesTest
{
    [TestClass()]
    public class CollectionHelperTest
    {
        private TestContext testContextInstance;

        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        #region Test objects

        public class ObjectWithArray
        {
            private ItemObject[] children_ = new ItemObject[0];

            public ItemObject[] Children
            {
                get { return children_; }
                set { children_ = value; }
            }
        }

        public class ObjectWithList
        {
            private List<ItemObject> children_ = new List<ItemObject>();

            public List<ItemObject> Children
            {
                get { return children_; }
                set { children_ = value; }
            }
        }

        public class ObjectWithDictionary
        {
            private Dictionary<int, ItemObject> children_ = new Dictionary<int, ItemObject>();

            [DictionaryItem(KeyName = "Id")]
            public Dictionary<int, ItemObject> Children
            {
                get { return children_; }
                set { children_ = value; }
            }
        }

        public class ItemObject
        {
            private int id_;

            public int Id
            {
                get { return id_; }
                set { id_ = value; }
            }

            private String name_;

            public String Name
            {
                get { return name_; }
                set { name_ = value; }
            }
        } 

        #endregion

        #region Array tests

        [TestMethod()]
        [ExpectedException(typeof(NotSupportedException))]
        public void CollectionHelperAddItemToArrayTest()
        {
            ObjectWithArray parent = new ObjectWithArray();

            ItemObject child = new ItemObject();
            child.Id = 1;
            child.Name = "Child";

            CollectionHelper.AddItem(null, null, parent.Children, child);
        }

        [TestMethod()]
        [ExpectedException(typeof(NotSupportedException))]
        public void CollectionHelperRemoveItemFromArrayTest()
        {
            ObjectWithArray parent = new ObjectWithArray();
            parent.Children = new ItemObject[1];

            ItemObject child = new ItemObject();
            child.Id = 1;
            child.Name = "Child";

            parent.Children[0] = child;

            CollectionHelper.RemoveItem(null, null, parent.Children, child);

            Assert.AreEqual(0, parent.Children.Length);
        }

        [TestMethod()]
        public void CollectionHelperSwapItemsInArrayTest()
        {
            ObjectWithArray parent = new ObjectWithArray();
            parent.Children = new ItemObject[2];

            ItemObject child1 = new ItemObject();
            child1.Id = 1;
            child1.Name = "Child1";
            parent.Children[0] = child1;

            ItemObject child2 = new ItemObject();
            child2.Id = 2;
            child2.Name = "Child2";
            parent.Children[1] = child2;

            CollectionHelper.SwapItems(parent.Children, 0, 1);

            Assert.AreEqual(2, parent.Children.Length);
            Assert.AreEqual(child1, parent.Children[1]);
            Assert.AreEqual(child2, parent.Children[0]);
        }

        [TestMethod()]
        public void CollectionHelperReplaceItemInArrayTest()
        {
            ObjectWithArray parent = new ObjectWithArray();
            parent.Children = new ItemObject[1];

            ItemObject child1 = new ItemObject();
            child1.Id = 1;
            child1.Name = "Child1";
            parent.Children[0] = child1;

            // Create the replacement child
            ItemObject child2 = new ItemObject();
            child2.Id = 2;
            child2.Name = "Child2";

            CollectionHelper.ReplaceItem(null, null, parent.Children, child1, child2);

            Assert.AreEqual(1, parent.Children.Length);
            Assert.AreEqual(child2, parent.Children[0]);
        }

        #endregion

        #region List tests

        [TestMethod()]
        public void CollectionHelperAddItemToListTest()
        {
            ObjectWithList parent = new ObjectWithList();

            ItemObject child = new ItemObject();
            child.Id = 1;
            child.Name = "Child";

            CollectionHelper.AddItemToList(parent.Children, child);

            Assert.AreEqual(1, parent.Children.Count);
            Assert.AreEqual(child, parent.Children[0]);
        }

        [TestMethod()]
        public void CollectionHelperRemoveItemFromListTest()
        {
            ObjectWithList parent = new ObjectWithList();

            ItemObject child = new ItemObject();
            child.Id = 1;
            child.Name = "Child";

            parent.Children.Add(child);

            CollectionHelper.RemoveItemFromList(parent.Children, child);

            Assert.AreEqual(0, parent.Children.Count);
        }

        [TestMethod()]
        public void CollectionHelperSwapItemsInListTest()
        {
            ObjectWithList parent = new ObjectWithList();

            ItemObject child1 = new ItemObject();
            child1.Id = 1;
            child1.Name = "Child1";
            parent.Children.Add(child1);

            ItemObject child2 = new ItemObject();
            child2.Id = 2;
            child2.Name = "Child2";
            parent.Children.Add(child2);

            int i = parent.Children.IndexOf(child1);
            int j = parent.Children.IndexOf(child2);

            CollectionHelper.SwapItems(parent.Children, 0, 1);

            Assert.AreEqual(2, parent.Children.Count);
            Assert.AreEqual(j, parent.Children.IndexOf(child1));
            Assert.AreEqual(i, parent.Children.IndexOf(child2));
        }

        [TestMethod()]
        public void CollectionHelperReplaceItemInListTest()
        {
            ObjectWithList parent = new ObjectWithList();

            ItemObject child1 = new ItemObject();
            child1.Id = 1;
            child1.Name = "Child1";
            parent.Children.Add(child1);

            // Create the replacement child
            ItemObject child2 = new ItemObject();
            child2.Id = 2;
            child2.Name = "Child2";

            CollectionHelper.ReplaceItemInList(parent.Children, child1, child2);

            Assert.AreEqual(1, parent.Children.Count);
            Assert.AreEqual(child2, parent.Children[0]);
        } 

        #endregion

        #region Dictionary tests

        [TestMethod()]
        public void CollectionHelperAddItemToDictionaryTest()
        {
            ObjectWithDictionary parent = new ObjectWithDictionary();

            ItemObject child = new ItemObject();
            child.Id = 1;
            child.Name = "Child";

            CollectionHelper.AddItem(parent, "Children", parent.Children, child);

            Assert.AreEqual(1, parent.Children.Count);
            Assert.AreEqual(child, parent.Children[1]);
        }

        [TestMethod()]
        public void CollectionHelperRemoveItemFromDictionaryTest()
        {
            ObjectWithDictionary parent = new ObjectWithDictionary();

            ItemObject child = new ItemObject();
            child.Id = 1;
            child.Name = "Child";

            parent.Children.Add(1, child);

            CollectionHelper.RemoveItem(parent, "Children", parent.Children, child);

            Assert.AreEqual(0, parent.Children.Count);
        }

        [TestMethod()]
        [ExpectedException(typeof(InvalidOperationException))]
        public void CollectionHelperSwapItemsInDictionaryTest()
        {
            ObjectWithDictionary parent = new ObjectWithDictionary();

            ItemObject child1 = new ItemObject();
            child1.Id = 1;
            child1.Name = "Child1";
            parent.Children.Add(1, child1);

            ItemObject child2 = new ItemObject();
            child2.Id = 2;
            child2.Name = "Child2";
            parent.Children.Add(2, child2);

            CollectionHelper.SwapItems(parent.Children, 0, 1);
        }

        [TestMethod()]
        public void CollectionHelperReplaceItemInDictionaryTest()
        {
            ObjectWithDictionary parent = new ObjectWithDictionary();

            ItemObject child1 = new ItemObject();
            child1.Id = 1;
            child1.Name = "Child1";
            parent.Children.Add(1, child1);

            // Create the child to replace
            ItemObject child2 = new ItemObject();
            child2.Id = 2; // Pay attention that the id value does not correspond to the key to be replaced, currently we don't verify that
            child2.Name = "Child2";

            CollectionHelper.ReplaceItem(parent, "Children", parent.Children, child1, child2);

            Assert.AreEqual(1, parent.Children.Count);
            Assert.AreEqual(child2, parent.Children[1]);
        }

        #endregion
    }
}
